package com.metersbonwe.basetest.core;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.ThreadFactory;

public class TestClient {
	/**
	 * 线程数
	 */
	private int threadCount = 0;

	/**
	 * 单个线程循环次数
	 */
	private int whileCount = 0;

	private CountDownLatch countDownLatch;

	private Class<?> clazz;

	private ExecutorService exec;
	/**
	 * 线程任务
	 */
	private List<Task> tasks;

	/**
	 * 
	 * @param threadCount
	 *            线程数量
	 * @param whileCount
	 *            循环次数
	 * @param classFullName
	 *            任务类名称
	 * @throws ClassNotFoundException
	 * @throws IllegalAccessException
	 * @throws InstantiationException
	 */
	public TestClient(int threadCount, int whileCount, String classFullName) throws ClassNotFoundException,
			InstantiationException, IllegalAccessException {
		this(threadCount, whileCount, Class.forName(classFullName));
	}

	/**
	 * 
	 * @param threadCount
	 *            线程数量
	 * @param whileCount
	 *            循环次数
	 * @param clazz
	 *            任务类
	 * @throws InstantiationException
	 * @throws IllegalAccessException
	 */
	public TestClient(int threadCount, int whileCount, Class<?> clazz) throws InstantiationException,
			IllegalAccessException {
		this.threadCount = threadCount;
		this.whileCount = whileCount;
		this.clazz = clazz;
		init();
		initTaskClass();
	}
	
	
	
	public TestClient(int threadCount, int whileCount) throws InstantiationException, IllegalAccessException {
		this.threadCount = threadCount;
		this.whileCount = whileCount;
		init();
	}

	
	void addTaskClass(Object obj) {
		Task task = (Task)obj;
		task.index = tasks.size() * this.whileCount;
		task.setCountDownLatch(countDownLatch);
		task.setRunCount(whileCount);
		tasks.add(task);
	}

	static volatile int ti=0;

	public void init() throws InstantiationException, IllegalAccessException {
		countDownLatch = new CountDownLatch(threadCount);
		tasks = new ArrayList<Task>(threadCount);
		exec = java.util.concurrent.Executors.newFixedThreadPool(threadCount,new ThreadFactory() {
			public Thread newThread(Runnable r) {
				Thread thread = new Thread(r);
				thread.setName("Test Thread " + ti++);
				return thread;
			}
		});
	}

	private void initTaskClass() throws InstantiationException, IllegalAccessException {
		if (!(clazz.newInstance() instanceof Task))
			throw new ClassCastException();
		for (int i = 0; i < threadCount; i++) {
			Task task = (Task) clazz.newInstance();
			task.index = i * this.whileCount;
			task.setCountDownLatch(countDownLatch);
			task.setRunCount(whileCount);
			tasks.add(task);
		}
	}

	public void run() throws InterruptedException {
		for (int i = 0; i < tasks.size(); i++) {
			Task array_element = tasks.get(i);
			exec.execute(array_element);
		}
		countDownLatch.await();
		display();
		if (!exec.isShutdown())
			exec.shutdown();
	}

	/** 总时间 */
	private long maxtime = 0;

	private double avgtime = 0;

	private long c1 = 0, c2 = 0, c3 = 0, c4 = 0, c5 = 0, c6 = 0;

	private long sc = 0;// 成功次数

	public void display() {
		long alltime = 0;
		for (int i = 0; i < tasks.size(); i++) {
			Task array_element = tasks.get(i);
			c1 += array_element.getLvl1_c();
			c2 += array_element.getLvl2_c();
			c3 += array_element.getLvl3_c();
			c4 += array_element.getLvl4_c();
			c5 += array_element.getLvl5_c();
			c6 += array_element.getLvl6_c();
			sc += array_element.getS_count();
			alltime += array_element.getAlltime();
			maxtime = array_element.getAlltime() > maxtime ? array_element.getAlltime() : maxtime;
		}
		avgtime = alltime / ((double) allcountm());
		showline();
		showInfo();
		showlvlInfo();
		showline();
	}

	public void show(String msg) {
		System.out.println(msg);
	}

	public void showline() {
		show("#########################################");
	}

	public void showlvlInfo() {
		show("响应时间区间\t\t比重\t次数");
		show(" (" + Task.lvl1 + "," + Task.lvl1 + "] ：\t" + c1 / (double) allcountm() + ",\t" + c1);
		show(" (" + Task.lvl1 + "," + Task.lvl2 + "] ：\t" + c2 / (double) allcountm() + ",\t" + c2);
		show(" (" + Task.lvl2 + "," + Task.lvl3 + "] ： \t" + c3 / (double) allcountm() + ",\t" + c3);
		show(" (" + Task.lvl3 + "," + Task.lvl4 + "] ： \t" + c4 / (double) allcountm() + ",\t" + c4);
		show(" (" + Task.lvl4 + "," + Task.lvl5 + "] ： \t" + c5 / (double) allcountm() + ",\t" + c5);
		show(" (" + Task.lvl5 + ",∞] ：\t" + c6 / (double) allcountm() + ",\t" + c6);
	}

	public void showInfo() {
		double maxtime_s = (double) maxtime / 1000;
		String info = " 总时间 ： " + maxtime + "毫秒,";
		info += " 线程数 ： " + threadCount + ",";
		info += " 总次数 ： " + allcountm() + ",";
		info += " 成功次数 ： " + sc + ",";
		info += " 平均响应时间 ： " + avgtime + "毫秒";
		info += " , 吞吐量  (次/秒)　  ：" + sc / maxtime_s;
		show(info);
	}

	/**
	 * 总次数
	 * 
	 * @return 总次数
	 */
	private double allcountm() {
		return threadCount * whileCount;
	}
}
